package org.algorithm.熊猫.回溯算法;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;

/**
 * n皇后问题 研究的是如何将 n个皇后放置在 n×n 的棋盘上，并且使皇后彼此之间不能相互攻击。
 * <p>
 * 给你一个整数 n ，返回所有不同的n皇后问题 的解决方案。
 * <p>
 * 每一种解法包含一个不同的n 皇后问题 的棋子放置方案，该方案中 'Q' 和 '.' 分别代表了皇后和空位。
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/n-queens
 */
public class $4月27日$N皇后复习 {

    @Test
    public void test() {
        System.out.println(solveNQueens(4));
    }


    public List<List<String>> solveNQueens(int n) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            sb.append(".");
        }
        ArrayList<String> board = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            board.add(i, sb.toString());
        }
        //初始化棋盘
        backtrack(board, 0);

        return res;
    }

    private List<List<String>> res = new ArrayList<>();

    void backtrack(ArrayList<String> board, int row) {

        //结束条件
        if (row == board.size()) {
            res.add((List<String>) board.clone());
            return;
        }
        int length = board.get(row).length();
        for (int col = 0; col < length; col++) {
            //是否合法
            if (!isValid(board, row, col)) {
                continue;
            }
            //做选择
            StringBuilder rowStr = new StringBuilder(board.get(row));
            rowStr.setCharAt(col, 'Q');
            board.set(row, rowStr.toString());

            //进入下一行选择
            backtrack(board, row + 1);

            //撤销选择
            rowStr.setCharAt(col, '.');
            board.set(row, rowStr.toString());
        }
    }

    private boolean isValid(List<String> board, int row, int col) {
        int size = board.size();

        //当前列是否有皇后
        for (int s = 0; s < size; s++) {
            if (board.get(s).charAt(col) == 'Q') {
                return false;
            }
        }
        //检查右上方是否有皇后
        for (int i = row - 1, j = col + 1; i >= 0 && j < size; i--, j++) {
            if (board.get(i).charAt(j) == 'Q') {
                return false;
            }
        }

        //检查左上方是否有皇后
        for (int i = row - 1, j = col - 1; i >= 0 && j >=0; i--, j--) {
            if (board.get(i).charAt(j) == 'Q') {
                return false;
            }
        }
        return true;

    }
}
